package interview_30

import (
	"fmt"
	"sync"
)

type MinStack struct {
	item []int
	l    sync.Mutex
	min  int
	s    []int
}

/** initialize your data structure here. */
func Constructor() MinStack {
	ms := MinStack{}
	return ms
}

func (m *MinStack) Push(x int) {
	m.l.Lock()
	defer m.l.Unlock()
	if len(m.item) == 0 {
		m.min = x
		m.s = append(m.s, x)
	}
	m.item = append(m.item, x)
	if x <= m.min {
		m.min = x
		m.s = append(m.s, x)
	}
}

func (m *MinStack) Pop() {
	m.l.Lock()
	defer m.l.Unlock()
	if len(m.item) == 0 {
		panic("item is empty")
	}
	el := m.item[len(m.item)-1]
	if m.min == el {
		m.s = m.s[:len(m.s)-1]
		m.min = m.s[len(m.s)-1]
	}
	m.item = m.item[:len(m.item)-1]
}

func (m *MinStack) Top() int {
	m.l.Lock()
	defer m.l.Unlock()
	if len(m.item) == 0 {
		panic("item is empty")
	}
	return m.item[len(m.item)-1]
}

func (m *MinStack) Min() int {
	if len(m.item) == 0 {
		panic("item is empty")
	}
	return m.min
}

func t1() bool {
	obj := Constructor()

	obj.Push(-2)
	obj.Push(0)
	obj.Push(-3)
	fmt.Println(obj.Min())
	obj.Pop()
	fmt.Println(obj.Top())
	fmt.Println(obj.Min())

	//obj.RPush(2)
	//obj.RPush(0)
	//obj.RPush(3)
	//obj.RPush(0)
	//log.Println(obj.Min())
	//obj.LPop()
	//log.Println(obj.Min())
	//obj.LPop()
	//log.Println(obj.Min())
	//obj.LPop()
	//log.Println(obj.Min())

	return false
}

/**
 * Your MinStack object will be instantiated and called as such:
 * obj := Constructor();
 * obj.RPush(x);
 * obj.LPop();
 * param_3 := obj.LTop();
 * param_4 := obj.Min();
 */
